home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Over 1,000 Windows 95 Programs
/
Over 1000 Windows 95 Programs (Microforum) (Disc 1).iso
/
0620
/
talk.txt
< prev
next >
Wrap
Text File
|
1997-04-06
|
14KB
|
425 lines
Talkline - How it works.
~~~~~~~~~~~~~~~~~~~~~~~~
Talkline is a sound of short duration, appended to the end of a message.
In this fist version, up to 5 seconds of sound can be added.
The purpose of this text file is to explain how the sound is coded
and appended to the message. This first version is called version "A" and
has the following characterization:
1-Sampling. - The sound bandwidth supports human voice only and so is sampled
at 5012.5Hz Hz, 8bits, with zero level at value 80h.
2-Compression -
A - The signal is converted to 4 bits, first subtracting DC value (80h) and
using a log (base 2) conversion of the absolute value:
in out
0 -> 0
0. .1 -> 1
2. .3 -> 2
4. .7 -> 3
8. .15 -> 4
16. .31 -> 5
32. .63 -> 6
64. .127 -> 7
Now the signal is 4 bits with zero level at 0 (-16 to 15).
B - The samples are packed 2 samples per byte, high nibble corresponding
to first sample and the low nibble to next one
EX:
t = 0 0000hhhh <-- 4 bit sample
1 0000LLLL
pack -> hhhhLLLL
C - Run lenght encoded, using FFh as flag character.
EX:
00 32 84 84 84 84 84 84 34 35 FF 54 54 FE FE FE FE FE FE
is converted to:
00 32 FF 05 84 34 35 FF 01 FF 54 54 FF 06 FE
3-Coding - The signal is coded using 7 bits, from 30h to AFh.
EX:
0 - AAAAaaaa - > 0 - 0AAAAaaa + 30h
1 - BBBBbbbb 1 - 0BBBBbbb + 30h
2 - CCCCcccc 2 - 0CCCCccc + 30h
3 - DDDDdddd 3 - 0DDDDddd + 30h
4 - EEEEeeee 4 - 0EEEEeee + 30h
5 - FFFFffff 5 - 0FFFFfff + 30h
6 - GGGGgggg 6 - 0GGGGggg + 30h
7 - 0abcdefg + 30h
4-Saving - The result is appended to the end of message at 64 bytes per line,
with a header:
"[TALK]" - 6 bytes - Identify a talkline
1Bh,"[8m" - 4 bytes - ANSI command to disable output, to avoid trash on
mail readers/terminal emulators without sound capabilities.
"A" - 1 byte - This version. Letters A to H are reserved.
"00000" - 5 bytes - The size of the sound in bytes, after coding and
without line feeds (E3h).
E3h - 1 byte - The character used as LF by the QWK file format.
.. follow first 64 bytes,E3h, and so on...
=========================================================================
As example, the routines, used to compress and expand the voice signal.
//-----------------------------------------------------------------------
UINT WaveCompress (LPSTR Pk, LPSTR Wav, UINT nS)
//
// Wav - intput signal
// Pk - output signal
// nS - number of data points
//
{
register UINT k, T;
char M;
UINT Ncomp, nS;
Log2(Wav, nS); ;4 bit convert
Ncomp = nS >> 1;
// pack data
_asm {
LES SI,Wav ;ES:SI -> Wav
MOV DI,SI
MOV CX,Ncomp
JCXZ DONE
L1: MOV AX,ES:[SI]
SHL AL,4 ;shift to HI nibble
AND AX,0FF0h ;mask
OR AL,AH ;merge
STOSB ;save
ADD SI,2
LOOP L1
DONE:
}
//
nS = 0;
Wav[Ncomp] = (char)(Wav[Ncomp-1]+1); //make last different
for(k=0; k<Ncomp; k++) //run lenght encode
{ T = 1;
M = Wav[k];
while (M == Wav[k+T]) //iqual next?
{ if(T == 253) break;
else T = T + 1; //yes, bump T
}
if(T > 2 || M == '\xFF')
{ Wav[nS++] = 0xFF; //mark
Wav[nS++] =(char)T; //total
k = k + T - 1; //next
}
Wav[nS++] = M; //save data
}
Ncomp = Pack(Pk, Wav, nS); //7 bits convert
return Ncomp;
}
//-----------------------------------------------------------------
LONG WaveExpand (LPSTR Wav, LPSTR Pk, UINT nS)
//
// Pk - input signal
// Wav - output signal
// nS - number of data points
//
{
register UINT T, k;
UINT Cnt;
LONG nExp, Pt;
//
nSamp = Unpack(Pk, Pk, nSamp); // 8 bits convert
nExp = 0; // run lenght decode
for(Pt=0; (UINT)Pt < nSamp; Pt++)
{ if(Pk[Pt] == (char) 0xFF )
{ Cnt = (BYTE) Pk[++Pt];
T = (char)Pk[++Pt];
for(k = 0; k < Cnt; k++) Wav[nExp++] = (char)T;
}
else
{ Wav[nExp++] = Pk[Pt]; }
}
Cnt =(UINT)nExp; //unpack
_asm {
LES DI, Wav
MOV BX,Cnt
OR BX,BX
JZ DONE
MOV SI,DI
ADD SI,BX ;end of data
ADD BX,BX ;end of unpacked data
L1: MOV AL,ES:[SI]
MOV AH,AL ;copy
SHR AL,4 ;do inverse operation
AND AX,0F0Fh ;mask
MOV ES:[DI+BX],AX ;save
DEC SI
SUB BX,2
JAE L1 ;for all data points
DONE:
}
//
nExp = nExp + nExp;
Exp2(Wave, nExp); ;8 bit convert
return nExp;
}
//=======================================================================
Assebly routines to convert to and from 7 bits.
;-------------------------------------------------------------------------
; UINT = Pack (LPSTR, LPSTR, UINT);
;
_Pack PROC FAR
PUSH BP
MOV BP,SP
PUSHF
CLD ;up
PUSH DS
PUSH SI
PUSH DI
XOR AX,AX ;zero return value
MOV CX,[BP+14] ;size (up to 64k)
JCXZ PACK9
LES DI,[BP+6];
LDS SI,[BP+10]; ;DS:SI -> string
XOR BX,BX ;byte count
ADD CX,SI ;offset end of input string
PUSH DI ;save it
;
PACK1: MOV DX,BX ;insert a 0E3h each 64 bytes
AND DX,3FH ;test
JNZ @F
MOV AL,0E3h ;LF (on QWK...)
STOSB ;insert
@@: CMP SI,CX ;end of processing?
JAE PACK2
LODSW ;-- 1 & 2
SHR AL,1 ;-> 7, bit 0 to CY
RCL DH,1 ;CY to bit 0 on DH
SHR AH,1 ;repeat to next byte
RCL DH,1
ADD AX,3030h ;translate to 30-A0h
STOSW ;ok, save it
LODSW
SHR AL,1 ;repeat for bytes 3 & 4
RCL DH,1
SHR AH,1
RCL DH,1
ADD AX,3030h
STOSW
LODSW
SHR AL,1 ;and 5 & 6
RCL DH,1
SHR AH,1
RCL DH,1
ADD AX,3030h
STOSW
LODSB
SHR AL,1 ;the last one...
RCL DH,1 ;
MOV AH,DH ;save DH (7 saved bits)
ADD AX,3030h ;
STOSW ;
ADD BX,8 ;total
JMP PACK1
PACK2: MOV AX,DI ;new position
POP DI ;initial position
SUB AX,DI ;return total processed bytes
PACK9: XOR DX,DX ;AX:DX
POP DI
POP SI
POP DS
POPF
MOV SP,BP
POP BP
RET
_Pack ENDP
;-------------------------------------------------------------
; UINT = Unpack (LPSTR, LPSTR, UINT);
;
_Unpack PROC FAR
PUSH BP
MOV BP,SP
PUSHF
PUSH DS
PUSH SI
PUSH DI
CLD ;up
XOR AX,AX
MOV CX,[BP+14] ;size
JCXZ UNPCK9
LES DI,[BP+6]; ;ES:DI -> string
LDS SI,[BP+10]; ;DS:SI -> string
PUSH DI
;
;UNPCK0: LODSB
; CMP AL,30H ;if out of range (30h -> AFh)
; JB @F ;do not copy
; CMP AL,0B0H
; JA @F
; STOSB
;@@: LOOP UNPCK0
;
UNPCK0: LODSB ;-- pcbord/qmail file corruption fix
CMP AL,30H
JAE @F
CMP AL,'#' ;<<<
JNE UNPK2
MOV AL,'@' ;<<<
@@: CMP AL,0B0H
JA UNPK2
STOSB
UNPK2: LOOP UNPCK0
; ;------------
MOV AX,DI
POP DI
SUB AX,DI ;total "clean" bytes
LDS SI,[BP+6]
LES DI,[BP+6] ;works only on destination
ADD AX,7
SHR AX,3 ;number of loops
MOV CX,AX
MOV BX,7
MUL BX ;number of bytes
MOV BX,AX ;save on BX
UNPCK1: MOV DH,[SI+7] ;get saved bit
SUB DH,30h ;convert to 0 - 7Fh
RCL DH,1
LODSW
SUB AX,3030h ;convert data too
RCL DH,1 ;bit -> CY
RCL AL,1 ;insert on byte
RCL DH,1 ;next byte
RCL AH,1
STOSW ;save
LODSW
SUB AX,3030h ;next 2 bytes
RCL DH,1
RCL AL,1
RCL DH,1
RCL AH,1
STOSW
LODSW
SUB AX,3030h ;bytes 5 & 6
RCL DH,1
RCL AL,1
RCL DH,1
RCL AH,1
STOSW
LODSW
SUB AL,30h ;the last...
RCL DH,1
RCL AL,1
STOSB
LOOP UNPCK1 ;repeat all
MOV AX,BX
UNPCK9: XOR DX,DX ;return total processed.
POP DI
POP SI
POP DS
POPF
MOV SP,BP
POP BP
RET
_Unpack ENDP
;---------------------------------------------------------------------
; Assembly routines to convert from 8 to 4 bits and from 4 to 8
;---------------------------------------------------------------------
; Log2 (LPSTR, UINT);
;
_Log2 PROC FAR
PUSH BP
MOV BP,SP
PUSHF
PUSH ES
PUSH DI
CLD
MOV BX,[BP+10] ;size to CX
OR BX,BX
JZ LOGC9
LES DI,[BP+6]; ;ES:DI -> in/out - in place conversion
LOGC1: MOV AL,ES:[DI]
XOR CH,CH ;zero
MOV DL,CH ;
sub al,80h ;remove DC value (-128..127)
OR AL,AL
JNS @F ;if positive, go
NEG AL ;signal change
MOV DL,8 ;signal bit
@@: AND AL,7FH
SHL AL,1
MOV CL,7
@@: SHL AL,1
JC @F
LOOP @B
@@: OR CL,DL ;insert signal
MOV AL,CL
;
STOSB ;save
DEC BX ;end test
JNZ LOGC1 ;no, more...
LOGC9: POP DI
POP ES
POPF
MOV SP,BP
POP BP
RET
_Log2 ENDP
;-------------------------------------------------------------------
; Exp2 (LPSTR, UINT);
;
_LogExp PROC FAR
PUSH BP
MOV BP,SP
PUSHF
PUSH ES
PUSH DI
CLD ;up
XOR AX,AX
MOV BX,[BP+10] ;size
OR BX,BX
JZ LOGE9
LES DI,[BP+6]; ;ES:DI -> in/out
XOR CH,CH
LOGE1: MOV AL,ES:[DI]
XOR AH,AH
;
MOV CL,AL ;copy
AND CL,7 ;signal mask
STC
RCL AH,CL ;exp
TEST AL,8
JZ @F ;if positive
NEG AH
@@: ADD AH,80H ;recover offset
MOV AL,AH
STOSB ;save
DEC BX
JNZ LOGE1 ;loop
LOGE9: POP DI
POP ES
POPF
MOV SP,BP
POP BP
RET
_Exp2 ENDP
;========================================================================
OBS: The music appended to the end of messages is a .MID file only coded
into 7 bits. The file header is the same, only the identifier "TALK"
change to "MIDI".
==========================================================================
Carlos Pires, Rio, March 1993.
==========================================================================
NOTE: Unpack routine correction to avoid file corruption over some BBSs
systems, the change of "@" by "#".
June, 1993.
==========================================================================